package com.ruoyi.system.condig;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

/**
 * 方法-SQL 关联上下文（基于 ThreadLocal 确保线程安全）
 */
public class MethodSqlContext {
    // 存储当前线程中正在执行的方法信息（被 @Log 标记的方法）
    // 主流日志框架（Logback、Log4j2、SLF4J）本身是线程安全的，其设计考虑了并发场景：
    //同步日志（默认）：通过锁机制保证同一时间只有一个线程写入日志，避免内容错乱。
    //异步日志：通过队列缓存日志事件，每个日志事件会携带当前线程的上下文信息（如通过 MDC 存储的线程标识），异步线程在输出时会正确关联原线程的上下文，确保日志归属正确。
    private static final ThreadLocal<MethodLogInfo> currentMethod = new ThreadLocal<>();

    // 存储当前方法执行过程中产生的 SQL 列表
    private static final ThreadLocal<List<SqlLogInfo>> methodSqls = ThreadLocal.withInitial(ArrayList::new);

    /**
     * 开始记录方法上下文
     */
    public static void startMethod(MethodLogInfo methodInfo) {
        currentMethod.set(methodInfo);
        methodSqls.get().clear(); // 清空上一次记录
    }

    /**
     * 记录当前方法执行的 SQL
     */
    public static void addSql(SqlLogInfo sqlInfo) {
        MethodLogInfo methodInfo = currentMethod.get();
        if (methodInfo != null) { // 仅当有活跃的方法上下文时记录
            sqlInfo.setMethodId(methodInfo.getMethodId()); // 关联方法ID
            methodSqls.get().add(sqlInfo);
        }
    }

    /**
     * 结束方法记录，返回该方法执行的所有 SQL
     */
    public static List<SqlLogInfo> endMethod() {
        List<SqlLogInfo> sqls = new ArrayList<>(methodSqls.get());
        // 清理线程变量，避免内存泄漏
        currentMethod.remove();
        methodSqls.get().clear();
        return sqls;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    // 内部类：方法日志信息
    public static class MethodLogInfo {
        private String methodId; // 方法唯一标识（如类名+方法名）
        private String logDesc; // @Log 注解的描述
        private long startTime; // 方法开始时间

        // 构造器和 getter/setter
        public MethodLogInfo(String methodId, String logDesc) {
            this.methodId = methodId;
            this.logDesc = logDesc;
            this.startTime = System.currentTimeMillis();
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    // 内部类：SQL 日志信息
    public static class SqlLogInfo {
        private String methodId; // 关联的方法ID
        private String sql; // SQL语句
        private long executeTimeMs; // SQL执行耗时
        private String operationType; // SELECT/INSERT等
    }
}